-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--         http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local ipmi = require 'manufacture.ipmi.cmds.GetTestItemInfo'
local factory = require 'factory'
local bs = require 'mc.bitstring'
local mc_ipmi = require 'ipmi'
local log = require "mc.logging"

local cc = mc_ipmi.types.Cc

local END_MASK = 0x80

local ipmi_handler = {}

local rsp_short_code = bs.new("<<dft_id, slot_id:32, dev_num, item_name:32/string>>")
local rsp_long_code = bs.new("<<dft_id, slot_id:32, dev_num, item_name:32/binary, prompt/string>>")

local function concat_rsp(obj)
    if not obj.PrompteReady or obj.PrompteReady == "" then
        return rsp_short_code:pack({dft_id = obj.Id,
                            slot_id = obj.Slot,
                            dev_num = obj.DeviceNum,
                            item_name = obj.ItemName})
    end
    local rsp = rsp_long_code:pack({dft_id = obj.Id,
                            slot_id = obj.Slot,
                            dev_num = obj.DeviceNum,
                            item_name = obj.ItemName,
                            prompt = obj.PrompteReady})
    return rsp
end
local function response_error(code)
    return ipmi.GetTestItemInfoRsp.new(code, END_MASK, "")
end

-- 根据offset返回结果
local function response_success(req, rsp_info)
    local read_offset = req.ReadOffset
    local read_length = req.ReadLength
    local total_length = #rsp_info
    local rsp = rsp_info
    local end_of_list = 0
    if read_offset + read_length < total_length then
        end_of_list = end_of_list & (~END_MASK)
        rsp = string.sub(rsp_info, read_offset, read_offset + read_length)
    else
        end_of_list = end_of_list | END_MASK
        rsp = string.sub(rsp_info, read_offset + 1)
    end
    return ipmi.GetTestItemInfoRsp.new(cc.Success, end_of_list, rsp)
end

local req_tail_code = bs.new("<<slot_id:32, dev_num>>")

function ipmi_handler.get_test_item_info_by_dftid(req, HostId)
    local manufacture_service = factory.get_obj("manufacture_service")
    local tail = req_tail_code:unpack(req.Tail)
    if not tail then
        return nil
    end
    local obj = manufacture_service:get_obj_by_dftid(req.Command, tail.slot_id, tail.dev_num, HostId)
    if not obj then
        return nil
    end
    return obj
end

function ipmi_handler.get_obj_by_req(req, HostId)
    if not req.Tail or req.Tail ~= "" then
        return ipmi_handler.get_test_item_info_by_dftid(req, HostId)
    end
    local manufacture_service = factory.get_obj("manufacture_service")
    -- 检查类型是否存在
    if not manufacture_service:check_type_exist(req.Type, HostId) then
        return nil
    end
    -- 通过下标找对应对象
    return manufacture_service:get_obj_form_type_list_by_count(req.Type, req.Command, HostId)
end

function ipmi_handler.get_test_item_info(req, ctx)
    log:debug("entry to get test item info")
    local obj = ipmi_handler.get_obj_by_req(req, ctx.HostId or 0)
    if not obj then
        return response_error(cc.UnspecifiedError)
    end
    local rsp_info = concat_rsp(obj)
    return response_success(req, rsp_info)
end

return ipmi_handler